#pragma once


/* Constants for huffman coding */
#define MAX_GROUPS			6
#define GROUP_SIZE   		50		/* 64 would have been more efficient */
#define MAX_HUFCODE_BITS 	20		/* Longest huffman code allowed */
#define MAX_SYMBOLS 		258		/* 256 literals + RUNA + RUNB */
#define SYMBOL_RUNA			0
#define SYMBOL_RUNB			1

/* Other housekeeping constants */
#define IOBUF_SIZE			4096




namespace micro
{
namespace qzip
{



class QBzipExtractor
{
    /* This is what we know about each huffman coding group */
    struct group_data
    {
        int		limit[MAX_HUFCODE_BITS];
        int		base[MAX_HUFCODE_BITS];
        int		permute[MAX_SYMBOLS];
        char	minLen;
        char	maxLen;
    };


    /* Input stream, input buffer, input bit buffer */
    QFile				m_file;
    QFile				m_fileDest;

    size_t				m_inbufCount;
    size_t				m_inbufPos;

    unsigned char		m_inbuf[IOBUF_SIZE];
    unsigned int		m_inbufBitCount;
    unsigned int		m_inbufBits;


    /* Output buffer */
    char				m_outbuf[IOBUF_SIZE];
    int					m_outbufPos;

    /* The CRC values stored in the block header and calculated from the data */
    unsigned int		m_crc32Table[256], m_headerCRC, m_dataCRC, m_totalCRC;

    /* Intermediate buffer and its size (in bytes) */
    unsigned int	*	m_dbuf, m_dbufSize;

    /* State for interrupting output loop */
    int					m_writePos, m_writeRun, m_writeCount, m_writeCurrent;

    /* These things are a bit too big to go on the stack */
    unsigned char		m_selectors[32768];			/* nSelectors=15 bits */
    group_data			m_groups[MAX_GROUPS];			/* huffman coding tables */

	
public:

    QBzipExtractor();
	 ~QBzipExtractor();
    bool	Extract( LPCTSTR source, LPCTSTR dest );

private:

    int				start_bunzip();
    unsigned int	get_bits( char bits_wanted );
    int				read_bunzip_data();
    int				write_bunzip_data( char * outbuf = nullptr, int len = 0 );
    void			flush_bunzip_outbuf();


};


}//
}//